#pragma once

#include <osg/Referenced>

class PramBase
{
public:
	PramBase(){}
	virtual ~PramBase(){}
};

template<typename P>
class Parm1:public PramBase
{
public:
	Parm1(P p)
	{
		_p = p;
	}
	virtual ~Parm1(){}
	virtual P getParm1()
	{
		return _p;
	}
private:
	P _p;
};

template<typename P1,typename P2>
class Parm2:public PramBase
{
public:
	Parm2(P1 p1,P2 p2)
	{
		_p1 = p1;
		_p2 = p2;
	}
	virtual ~Parm2(){}
	virtual P1 getParm1()
	{
		return _p1;
	}
	virtual P2 getParm2()
	{
		return _p2;
	}
private:
	P1 _p1;
	P2 _p2;
};

class FuncBase:public osg::Referenced
{
public:
	FuncBase(){}
	~FuncBase(){}
	virtual void callFunc()
	{}
	virtual void callFunc(PramBase* p)
	{}
};

template<typename R,typename T>
class VoidFunc:public FuncBase
{
public:
	typedef R (T::*function)();
	VoidFunc(function func,T* obj)
	{
		_func = func;
		_obj = obj;
	}
	~VoidFunc(){}
	virtual void callFunc()
	{
		(_obj->*_func)();
	}
	virtual R callReturnFunc()
	{
		return (_obj->*_func)();
	}
private:
	function	_func;
	T*			_obj;
};

template<typename R,typename T,typename P>
class Type_1Func:public FuncBase
{
public:
	typedef R (T::*function)(P p);
	Type_1Func(function func,T* obj,P p1)
	{
		_func = func;
		_obj = obj;
		_p = p1;
	}
	Type_1Func(function func,T* obj)
	{
		_func = func;
		_obj = obj;
	}
	~Type_1Func(){}
	virtual void callFunc()
	{
		(_obj->*_func)(_p);
	}
	virtual void callFunc(PramBase* p)
	{
		(_obj->*_func)(dynamic_cast<Parm1<P>*>(p)->getParm1());
		delete p;
		p = NULL;
	}
private:
	function	_func;
	T*			_obj;
	P			_p;
};

template<typename R,typename T,typename P1,typename P2>
class Type_2Func:public FuncBase
{
public:
	typedef R (T::*function)(P1 p1,P2 p2);
	Type_2Func(function func,T* obj,P1 p1,P2 p2)
	{
		_func = func;
		_obj = obj;
		_p1 = p1;
		_p2 = p2;
	}
	~Type_2Func(){}
	virtual void callFunc()
	{
		(_obj->*_func)(_p1,_p2);
	}
	virtual void callFunc(PramBase* p)
	{
		(_obj->*_func)(dynamic_cast<Parm2<P1,P2>*>(p)->getParm1(),dynamic_cast<Parm2<P1,P2>*>(p)->getParm2());
		delete p;
		p = NULL;
	}
private:
	function	_func;
	T*			_obj;
	P1			_p1;
	P2			_p2;
};